#include "gamewindow.hpp"

#include <QMessageBox>

GameWindow::GameWindow(Client * client, Game * game, MainWindow * mainWindow, QWidget *parent) :
    QMainWindow(parent),
    _client(client),
    _game(game),
    _mainWindow(mainWindow),
    _isFinished(false)
{
    _dockGoban = new QDockWidget(this);
    _dockPlayers = new QDockWidget(this);
    _dockScore = new QDockWidget(this);
    _dockChat = new QDockWidget(this);
    _dockButtons = new QDockWidget(this);

    _dockGobanContent = new GobanView(_client, this, _game->size(), _game->goban());
    _dockPlayersContent = new QListWidget(this);
    _dockScoreContent = new QWidget(this);
    _dockChatContent = new QWidget(this);
    _dockButtonsContent = new QWidget(this);

    _dockGoban->setFeatures(QDockWidget::NoDockWidgetFeatures);
    _dockPlayers->setFeatures(QDockWidget::NoDockWidgetFeatures);
    _dockScore->setFeatures(QDockWidget::NoDockWidgetFeatures);
    _dockChat->setFeatures(QDockWidget::NoDockWidgetFeatures);
    _dockButtons->setFeatures((QDockWidget::NoDockWidgetFeatures));

    _gobanTitle = new QLabel("Goban", this);
    _playersTitle = new QLabel("Players", this);
    _scoreTitle = new QLabel("Score", this);
    _chatTitle = new QLabel("Chat", this);
    _buttonsTitle = new QLabel("Actions", this);

    _dockScoreLayout = new QGridLayout(_dockScoreContent);
    _dockChatLayout = new QGridLayout(_dockChatContent);
    _dockButtonsLayout = new QGridLayout(_dockButtonsContent);

    _dockScoreContent->setLayout(_dockScoreLayout);
    _dockChatContent->setLayout(_dockChatLayout);
    _dockButtonsContent->setLayout(_dockButtonsLayout);

    _blackStone = new QLabel(this);
    _blackName = new QLabel("Black", this);
    _blackScore = new QLabel("0", this);
    _whiteStone = new QLabel(this);
    _whiteName = new QLabel("White", this);
    _whiteScore = new QLabel(QString::number(_game->komi()), this);

    QPixmap black("img/black.png");
    QPixmap white("img/white.png");

    black = black.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    white = white.scaled(32, 32, Qt::KeepAspectRatio, Qt::SmoothTransformation);

    _blackStone->setPixmap(black);
    _whiteStone->setPixmap(white);

    _listMessages = new QListWidget(this);
    _message = new QLineEdit(this);
    _send = new QPushButton("Send", this);
    _skip = new QPushButton("Skip", this);
    _validate = new QPushButton("Validate", this);
    _cancel = new QPushButton("Back to game", this);

    _dockButtonsContent->setMaximumWidth(150);

    _dockScoreLayout->addWidget(_blackStone, 0, 0);
    _dockScoreLayout->addWidget(_blackName, 0, 1);
    _dockScoreLayout->addWidget(_blackScore, 0, 2);
    _dockScoreLayout->addWidget(_whiteStone, 1, 0);
    _dockScoreLayout->addWidget(_whiteName, 1, 1);
    _dockScoreLayout->addWidget(_whiteScore, 1, 2);

    _dockChatLayout->addWidget(_listMessages, 0, 0, 1, 3);
    _dockChatLayout->addWidget(_message, 1, 0, 1, 2);
    _dockChatLayout->addWidget(_send, 1, 2);

    _dockButtonsLayout->addWidget(_skip, 0, 0);
    _dockButtonsLayout->addWidget(_validate, 1, 0);
    _dockButtonsLayout->addWidget(_cancel, 2, 0);

    _validate->hide();
    _cancel->hide();

    _dockGoban->setWidget(_dockGobanContent);
    _dockPlayers->setWidget(_dockPlayersContent);
    _dockScore->setWidget(_dockScoreContent);
    _dockChat->setWidget(_dockChatContent);
    _dockButtons->setWidget(_dockButtonsContent);

    _dockGoban->setTitleBarWidget(_gobanTitle);
    _dockPlayers->setTitleBarWidget(_playersTitle);
    _dockScore->setTitleBarWidget(_scoreTitle);
    _dockChat->setTitleBarWidget(_chatTitle);
    _dockButtons->setTitleBarWidget(_buttonsTitle);

    _gobanTitle->setContentsMargins(10, 5, 25, 0);
    _playersTitle->setContentsMargins(10, 5, 25, 0);
    _scoreTitle->setContentsMargins(10, 5, 25, 0);
    _chatTitle->setContentsMargins(10, 5, 25, 0);
    _buttonsTitle->setContentsMargins(10, 5, 25, 0);

    addDockWidget(Qt::LeftDockWidgetArea, _dockGoban);
    addDockWidget(Qt::RightDockWidgetArea, _dockPlayers);
    addDockWidget(Qt::RightDockWidgetArea, _dockButtons);
    addDockWidget(Qt::RightDockWidgetArea, _dockScore);
    addDockWidget(Qt::RightDockWidgetArea, _dockChat);

    connect(_send, SIGNAL(clicked()), this, SLOT(reactSendClicked()));
    connect(_skip, SIGNAL(clicked()), this, SLOT(reactSkipPressed()));
    connect(_validate, SIGNAL(clicked()), this, SLOT(reactValidatePressed()));
    connect(_cancel, SIGNAL(clicked()), this, SLOT(reactCancelClicked()));

    reactUpdatePlayer();

    if (_blackName->text() != _mainWindow->windowTitle() and
        _whiteName->text().isEmpty())
    {
        if (QMessageBox::question(this, "Question", "This game has not started yet.\nDo you want to play it?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
            _client->send(Mid::WANTTOPLAY, _game->id());
        else
            _client->send(Mid::WANTTOSEE, game->id());
    }
    else if (_game->isStarted())
        _client->send(Mid::WANTTOSEE, game->id());
}

void GameWindow::displayBadMove()
{
    QMessageBox::information(this, "Information", "This is not a valid move!");
}

GameWindow::~GameWindow()
{
    _game->clearObservers();

}

quint8 GameWindow::id() const
{
    return _game->id();
}

Game * GameWindow::game() const
{
    return _game;
}

Client * GameWindow::client() const
{
    return _client;
}

void GameWindow::reactUpdatePlayer()
{
    _dockPlayersContent->clear();

    _blackName->setText(_game->black());
    _whiteName->setText(_game->white());

    _dockPlayersContent->addItem(_game->black());
    if (!_game->white().isEmpty())
        _dockPlayersContent->addItem(_game->white());
    _dockPlayersContent->addItems(_game->observers());

    if (_blackName->text() == _mainWindow->windowTitle() or _whiteName->text() == _mainWindow->windowTitle())
        _dockButtons->show();
}

void GameWindow::heLeft(quint8 playerID)
{
    _isFinished = true;

    QString loserName, winnerName;
    if (playerID == 0)
    {
        loserName = _blackName->text();
        winnerName = _whiteName->text();
    }
    else
    {
        loserName = _whiteName->text();
        winnerName = _blackName->text();
    }

    if (QMessageBox::question(this, "Information", loserName + " left the game!\n" + winnerName + " wins!\nDo you want to close the game window?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
        close();
}

void GameWindow::gameDestroyed()
{
    if (!_isFinished)
    {
        if (QMessageBox::question(this, "Information", "The game has been destroyed.\nDo you want to close it?", QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
            close();

        _isFinished = true;
    }
}

void GameWindow::closeEvent(QCloseEvent * event)
 {
    if (!_isFinished)
    {
        if (_blackName->text() == _mainWindow->windowTitle() or
            _whiteName->text() == _mainWindow->windowTitle()) // if I play in it
        {
            if (QMessageBox::information(this, "Confirmation", "Are you sure you want to quit that game?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
            {
                if (!_game->isStarted())
                    _client->send(Mid::GAMEDESTROY, _game->id());
                else
                    _client->send(Mid::GAMEQUIT, _game->id());

                emit closed(_game->id());
                event->accept();
            }
            else
            {
                event->ignore();
            }
        }
        else
        {
            _client->send(Mid::DONTWANTTOSEEANYMORE, _game->id());
            emit closed(_game->id());
            event->accept();
        }
    }
    else
    {
        emit closed(_game->id());
        event->accept();
    }
 }

void GameWindow::reactSendClicked()
{
    if (!_message->text().isEmpty() and !_isFinished)
    {
        _client->send(Mid::GAMESAY, _game->id(), _message->text());
        _message->clear();
    }
}

void GameWindow::someoneSaid(const QString & message)
{
    _listMessages->addItem(message);
}

void GameWindow::reactMovePlayed(quint8 playerID, quint8 x, quint8 y)
{
    _game->goban()->playAMove(playerID==0, x, y);
    _dockGobanContent->addStone(x, y, playerID == 0);
    _game->switchBlackToPlay();
}

void GameWindow::setScore(quint8 playerID, qreal newScore)
{
    if (playerID == 0)
        _blackScore->setText(QString::number(newScore));
    else
        _whiteScore->setText(QString::number(newScore));
}

void GameWindow::reactSkipPressed()
{
    if (_game->isStarted() && !_game->isEstablishingScore() && !_game->isFinished() && meToPlay())
        _client->send(Mid::SKIPTURN, _game->id());
}

bool GameWindow::amIBlack() const
{
    return _blackName->text() == _mainWindow->windowTitle();
}

bool GameWindow::amIWhite() const
{
    return _whiteName->text() == _mainWindow->windowTitle();
}

bool GameWindow::meToPlay() const
{
    return (amIBlack() and _game->blackToPlay()) or (amIWhite() and !_game->blackToPlay());
}

void GameWindow::skipTurn()
{
    _game->switchBlackToPlay();
}

void GameWindow::reactGroupKilled(quint8 x, quint8 y)
{
    _game->goban()->declareDead(x, y);
}

void GameWindow::reactGroupSaved(quint8 x, quint8 y)
{
    _game->goban()->declareAlive(x, y);
}

void GameWindow::setEstablishingScore(bool isEstablishingScore)
{
    _game->setEstablishingScore(isEstablishingScore);

    if (isEstablishingScore)
    {
        _validate->show();
        _cancel->show();
        _skip->hide();
    }
    else
    {
        _validate->hide();
        _cancel->hide();
        _skip->show();
    }
}

void GameWindow::reactGroupsValidated(quint8 playerID)
{
    if (playerID == 0 and amIBlack())
        QMessageBox::information(this, "Information", "You have successfully validated!");
    else if (playerID == 0)
        QMessageBox::information(this, "Information", QString(_blackName->text() + " has validated!"));
    else if (playerID == 1 and amIWhite())
        QMessageBox::information(this, "Information", "You have successfully validated!");
    else
        QMessageBox::information(this, "Information", QString(_whiteName->text() + " has validated!"));
}

void GameWindow::reactToPlayAgain()
{
    _game->goban()->reactToPlayAgain();
}

void GameWindow::reactGameover(qreal blackScore, qreal whiteScore)
{
    QString winner;
    qreal diff;

    if (blackScore > whiteScore)
    {
        winner = _blackName->text();
        diff = blackScore - whiteScore;
    }
    else
    {
        winner = _whiteName->text();
        diff = whiteScore - blackScore;
    }

    setScore(0, blackScore);
    setScore(1, whiteScore);

    _isFinished = true;

    QMessageBox::information(this, "Information", QString(winner + " has won by " + QString::number(diff) + "points"));
}

void GameWindow::reactValidatePressed()
{
    _client->send(Mid::VALIDATEGROUPS, _game->id());
}

void GameWindow::reactCancelClicked()
{
    _client->send(Mid::TOPLAY, _game->id());
}
